﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xiaowei.Diagnostics;

namespace Xiaowei.Players.XiaoweiPlayerLib
{
    public enum ListOperation
    {
        Replace,
        EnqueueFront,
        EnqueueBack,
        RefreshUrl
    }
    public class XiaoweiPlayerManager
    {
        public event EventHandler<int> PositionChanged;
        public event EventHandler<PlayerState> PlayerStateChanged;
        public event EventHandler<int> DurationChanged;
        public event EventHandler<PlayMode> PlayModeChanged;
        public event EventHandler<string> ItemTitleChanged;
        public event EventHandler<XiaoweiPlayerItemBase> CurrentItemChanged;
        public event EventHandler<bool> CanGoPreChanged;
        public event EventHandler<bool> CanGoNextChanged;
        public delegate void ListChangedHandle(IXiaoweiPlayerList list, ListOperation operation);
        public event ListChangedHandle ListChanged;
        public event EventHandler CloseEvent;
        public event EventHandler MinimizeEvent;
        public event EventHandler SuspendEvent;

        private static Lazy<XiaoweiPlayerManager> lazyXiaoweiPlayerManager = new Lazy<XiaoweiPlayerManager>(new XiaoweiPlayerManager());
        public static XiaoweiPlayerManager Instance => lazyXiaoweiPlayerManager.Value;
        public XiaoweiPlayerAudio XiaoweiPlayerAudio { get; private set; }
        private XiaoweiPlayerManager()
        {
            XiaoweiPlayerAudio = new XiaoweiPlayerAudio();
            XiaoweiPlayerAudio.DurationChanged += XiaoweiPlayerAudio_DurationChanged;
            XiaoweiPlayerAudio.PlayerStateChanged += XiaoweiPlayerAudio_PlayerStateChanged;
            XiaoweiPlayerAudio.PositionChanged += XiaoweiPlayerAudio_PositionChanged;
        }
        private void XiaoweiPlayerAudio_PositionChanged(object sender, EventArgs e)
        {
            PositionChanged?.Invoke(this,(int)XiaoweiPlayerAudio.Position.TotalSeconds);
            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList3 list3)
            {
                list3.CurrentTime= (int)XiaoweiPlayerAudio.Position.TotalSeconds;
            }
        }
        private void XiaoweiPlayerAudio_PlayerStateChanged(object sender, EventArgs e)
        {
            PlayerStateChanged?.Invoke(this, XiaoweiPlayerAudio.PlayerState);
            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList3 list3)
            {
                list3.PlayerState = XiaoweiPlayerAudio.PlayerState;
            }
        }
        private void XiaoweiPlayerAudio_DurationChanged(object sender, EventArgs e)
        {
            DurationChanged?.Invoke(this, (int)XiaoweiPlayerAudio.Duration.TotalSeconds);
            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList3 list3)
            {
                list3.Duration = (int)XiaoweiPlayerAudio.Duration.TotalSeconds;
            }
        }
        public void Close()
        {
            XiaoweiPlayerAudio.XiaoweiPlayerList = null;
            CloseEvent?.Invoke(this, EventArgs.Empty);
            IsClosed = true;
        }
        public void SetPlayItem(XiaoweiPlayerItemBase currentItem)
        {
            
            if(XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList2 list2)
            {
                if (list2.Collection.Count == 0) return;
                list2.CurrentItem = currentItem;
            }
        }
        public void SwitchPlayPause()
        {
            if(XiaoweiPlayerAudio.PlayerState==PlayerState.Play)
            {
                XiaoweiPlayerAudio.Pause();
            }
            else
            {
                XiaoweiPlayerAudio.Play();
            }
        }
        public void GetMoreDown()
        {
            if(XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList2 list2)
            {
                list2.GetMoreDown();
            }
        }
        public void GetMoreUp()
        {
            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList2 list2)
            {
                list2.GetMoreUp();
            }
        }
        public void PlayModeChange()
        {
            PlayMode = XiaoweiPlayerAudio.XiaoweiPlayerList.SwitchPlayMode();
        }
        public void GoPre()
        {
            XiaoweiPlayerAudio.Prev();
        }
        public void GoNext()
        {
            XiaoweiPlayerAudio.Next();
        }
        private void ReplaceList(IXiaoweiPlayerList list)
        {
            if(XiaoweiPlayerAudio.XiaoweiPlayerList!=null)
            {
                XiaoweiPlayerAudio.XiaoweiPlayerList.CanGoNextChanged -= List_CanGoNextChanged;
                XiaoweiPlayerAudio.XiaoweiPlayerList.CanGoPreChanged -= List_CanGoPreChanged;
                XiaoweiPlayerAudio.XiaoweiPlayerList.CurrentItemChanged -= List_CurrentItemChanged;
            }

            XiaoweiPlayerAudio.XiaoweiPlayerList = list;
            if (list != null)
            {
                list.CanGoNextChanged += List_CanGoNextChanged;
                list.CanGoPreChanged += List_CanGoPreChanged;
                list.CurrentItemChanged += List_CurrentItemChanged;
                PlayMode = list.PlayMode;
            }
            if (list?.CurrentItem != null)
            {
                CanGoNextChanged?.Invoke(this,list.CanGoNext);
                CanGoPreChanged?.Invoke(this, list.CanGoPre);
                ItemTitleChanged?.Invoke(this, list.CurrentItem.Title);
            }
            Debug.WriteLine("ReplaceList end");
        }
        private void List_CurrentItemChanged(object sender, XiaoweiPlayerItemBase e)
        {
            if (e != null)
            {
                ItemTitleChanged?.Invoke(this, e.Title);

            }
            if (sender is IXiaoweiPlayerList2 list2)
            {
                CurrentItemChanged?.Invoke(this, e);
            }
        }
        private void List_CanGoPreChanged(object sender, EventArgs e)
        {
            CanGoPreChanged?.Invoke(this, ((IXiaoweiPlayerList)sender).CanGoPre);
        }
        private void List_CanGoNextChanged(object sender, EventArgs e)
        {
            CanGoNextChanged?.Invoke(this,((IXiaoweiPlayerList)sender).CanGoNext);
        }
        public void OperateList(IXiaoweiPlayerList list, ListOperation operation)
        {
            Debug.WriteLine($"OperateList, operation:{operation}");
            ListChanged?.Invoke(list, operation);
            if (XiaoweiPlayerAudio.XiaoweiPlayerList == null)
            {
                ReplaceList(list);
            }
            else
            {
                switch (operation)
                {
                    case ListOperation.Replace:
                        ReplaceList(list);
                        break;
                    case ListOperation.EnqueueFront:
                        {
                            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList2 list2 && list is IXiaoweiPlayerList2 list3)
                            {
                                list2.EnqueueFront(list3);
                            }
                        }
                        break;
                    case ListOperation.EnqueueBack:
                        {
                            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList2 list2 && list is IXiaoweiPlayerList2 list3)
                            {
                                list2.EnqueueBack(list3);
                            }
                        }
                        break;
                    case ListOperation.RefreshUrl:
                        {
                            if (XiaoweiPlayerAudio.XiaoweiPlayerList is IXiaoweiPlayerList2 list2 && list is IXiaoweiPlayerList2 list3)
                            {
                                list2.RefreshURL(list3);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            
        }
        public void SetPlayMode(PlayMode playMode)
        {
            if(XiaoweiPlayerAudio.XiaoweiPlayerList.TryToChangePlayMode(playMode))
            {
                PlayMode = playMode;
            }
        }
        private PlayMode playMode= PlayMode.LoopPlay;
        public PlayMode PlayMode { 
            get {
                return playMode;
            }
            private set 
            {
                if(playMode!=value)
                {
                    playMode = value;
                    PlayModeChanged?.Invoke(this, playMode);
                }
                
            }
        }
        public void Minimize()
        {
            MinimizeEvent?.Invoke(this, EventArgs.Empty);
        }
        public void Suspend()
        {
            SuspendEvent?.Invoke(this, EventArgs.Empty);
        }
        public event EventHandler ResumeEvent;
        public void Resume()
        {
            ResumeEvent?.Invoke(this, EventArgs.Empty);
        }
        public event EventHandler LaunchEvent;
        public void Launch()
        {
            LaunchEvent?.Invoke(this, EventArgs.Empty);
            IsClosed = false;
        }
        public bool IsClosed { get; private set; } = true;
    }
}
